
package com.insigma.business.common.controller;

import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.insigma.business.common.dto.CurrentUser;
import com.insigma.business.common.utils.AnnotationUtils;
import com.insigma.business.common.utils.CurrentUserUtil;
import com.insigma.business.common.utils.ToolsHelper;
import com.insigma.business.gateway.dto.MethodClassDTO;
import com.insigma.business.qrcode.common.dao.SoldierInsertLogDao;
import com.insigma.business.qrcode.common.dto.SoldierInsertLogDO;
import com.insigma.business.qrcode.common.template.area.ScenarioCodeEnum;
import com.insigma.business.qrcode.common.template.area.ServiceCallback;
import com.insigma.business.qrcode.common.util.*;
import com.insigma.business.qrcode.common.vo.*;
import com.insigma.business.common.dto.LoggedInSoldierPersistentVO;
import com.insigma.business.qrcode.soldier.dto.RequestObjFO;
import com.insigma.business.gateway.template.CheckValidManager;
import com.insigma.business.common.service.SoldierGatewayManager;
import com.insigma.business.qrcode.soldier.util.SoldierConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;


@Slf4j
@RestController("soldierGatewayController")
@RequestMapping("/v1/ss/soldier/gw")
public class SoldierGatewayController extends BaseGatewayController {

    @Autowired
    @Qualifier("soldierGatewayAndCheckManager")
    private CheckValidManager soldierCheckValidManager;
    @Autowired
    @Qualifier("soldierGatewayAndCheckManager")
    private SoldierGatewayManager soldierGatewayManager;
    @Autowired(required = false)
    private SoldierInsertLogDao soldierInsertLogDao;

    @PostMapping
    @SuppressWarnings("unchecked")
    public RestfulResult doPost(@RequestBody final RequestObjFO requestObj,
                                final HttpServletRequest request,
                                final HttpServletResponse response) {
        LogUtil.info(log, "请求参数：", requestObj.toString(),",token：",request.getHeader(SoldierConstant.SOLDIER_TOKEN_NAME));

        final long startMs = System.currentTimeMillis();
        final RestfulResult<Object>[] result = new RestfulResult[]{new RestfulResult<>()};
        final BaseResponse  Baseresult = new BaseResponse<>();
        CurrentUser currentUser = CurrentUserUtil.getCurrentUser();

        serviceTemplate.execute(result[0],new ServiceCallback() {
            @Override
            public void check() {
                soldierCheckValidManager.checkRequestParam(requestObj,false);

                soldierCheckValidManager.checkHack(requestObj.getOperation(),request.getHeader(SoldierConstant.SOLDIER_TOKEN_NAME));

                if(StringUtils.isNotBlank(request.getHeader(SoldierConstant.SOLDIER_VISITOR_ID))){
                    BizCheckUtil.checkIsTrue(request.getHeader(SoldierConstant.SOLDIER_VISITOR_ID).length() <= 128,"访客标记超长了");
                }
            }
            @Override
            public void executeService() {
                preHandle(request,requestObj);
                BaseResponse remoteResponse =new BaseResponse();
                try {
                    //记录日志
                    SoldierInsertLogDO record = new SoldierInsertLogDO();
                    record.setLoginIp(ToolsHelper.getClientIp(request));
                    record.setRequestParams(JSONObject.toJSONString(requestObj));
                    //设置操作内容及菜单
                    Map<String, MethodClassDTO> classBeanNameMap = AnnotationUtils.classBeanNameMap;
                    if (null != classBeanNameMap) {
                        for (Map.Entry<String, MethodClassDTO> stringMethodClassDTOEntry : classBeanNameMap.entrySet()) {
                            MethodClassDTO value = stringMethodClassDTOEntry.getValue();
                            if (requestObj.getOperation().contains(value.getValue())) {
                                record.setOperateContent(value.getName());
                                record.setMenu(value.getMenu());
                            }
                        }
                    }
                    record.setRequestUrl(request.getRequestURI());
                    record.setOperateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                    if (null != currentUser) {
                        record.setLoginUser(null != currentUser.getSoldierId() ? currentUser.getSoldierId() : null);
                        record.setLoginUserName(null != currentUser.getIdCardNo() ? currentUser.getIdCardNo() : null);
                    }
                    soldierInsertLogDao.insert(record);
                    //执行具体方法
                    remoteResponse=  soldierGatewayManager.executeService(requestObj);
                } catch (Exception e){
                    result[0] = RestfulResultUtil.buildFailed(RestfulCodeEnum.INTERNAL_ERROR, e.getMessage());
                    return;
                }

                postHandle(request,requestObj,remoteResponse);

//                if (!remoteResponse.getSuccess()){
//                    setupResult(Baseresult, result[0]);
//                }
                setupResult(remoteResponse, result[0]);
            }

            @Override
            public ScenarioCodeEnum getScenarioEnum() {
                return ScenarioCodeEnum.PLACEMENT_WORD_CONFIG_SEARCH;
            }
        });

        LogUtil.info(log, "访问服务:", requestObj.getOperation(), "返回结果为:", result[0].toString(),
                ",耗时(毫秒):", (System.currentTimeMillis() - startMs));
        return result[0];
    }


    @PostMapping("/mix")
    @SuppressWarnings("unchecked")
    public String doPostOfEncode(@RequestBody final RequestObjFO requestObj,
                                final HttpServletRequest request,
                                final HttpServletResponse response) throws UnsupportedEncodingException {
        RestfulResult restfulResult = doPost(requestObj, request, response);
        String encode = Base64.encode(JSON.toJSONString(restfulResult).getBytes(StandardCharsets.UTF_8));
        return encode;
    }


    @GetMapping
    public RestfulResult doGet(HttpServletRequest httpServletRequest,
                               HttpServletResponse httpServletResponse) {
             return RestfulResultUtil.buildFailed(RestfulCodeEnum.INTERNAL_ERROR, "暂不支持Get请求，请参考使用手册");
    }


    private void preHandle(final HttpServletRequest request, final RequestObjFO requestObj){
        LoggedInSoldierPersistentVO loggedIn = null;
        final String token = request.getHeader(SoldierConstant.SOLDIER_TOKEN_NAME);
        if (StringUtils.isNotBlank(token)) {
            loggedIn = (LoggedInSoldierPersistentVO)cacheManager.getCommonValue(SoldierConstant.CACHE_KEY_LOGGEDIN_SOLDIER_PREFIX + token,60);


            if(loggedIn==null){

                loggedIn = soldierGatewayManager.getLoggedInSoldierPersistentInfoByToken(token);
                if(loggedIn != null){
                    cacheManager.setCommonValue(SoldierConstant.CACHE_KEY_LOGGEDIN_SOLDIER_PREFIX + token, loggedIn);
                }
            }
        }

        if(loggedIn == null){
            if (!soldierCheckValidManager.isVisitorOperation(requestObj)) {
//                throw new AccessFailedException(String.valueOf(HttpStatus.UNAUTHORIZED.value()),"请登录后访问系统");
            }
        }else {

            final SessionSoldier sessionMember = buildSessionSoldier(request, requestObj, loggedIn);
            RpcContextUtil.setSessionSoldierStr(JSON.toJSONString(sessionMember));
        }


        final SessionBasis sessionBasis = super.buildSessionBasis(request, requestObj,
                UserTypeEnum.SOLDIER.name(),request.getHeader(SoldierConstant.SOLDIER_VISITOR_ID),null,null,null);
        RpcContextUtil.setSessionBasisStr(JSON.toJSONString(sessionBasis));
    }


    private SessionSoldier buildSessionSoldier(final HttpServletRequest request, final RequestObjFO requestObj, LoggedInSoldierPersistentVO loggedIn){
        final SessionSoldier sessionSoldier = new SessionSoldier();
        sessionSoldier.setUserType(UserTypeEnum.SOLDIER.name());
        sessionSoldier.setAuthorization(request.getHeader(SoldierConstant.SOLDIER_TOKEN_NAME));
        sessionSoldier.setEndType(requestObj.getSource());
        sessionSoldier.setEndIp(ClientUtil.getEndIp(request));
        sessionSoldier.setUserId(loggedIn.getUserId());
        sessionSoldier.setMobile(loggedIn.getMobile());
        sessionSoldier.setLatestAccessDatetime(new Date());
        sessionSoldier.setUserName(loggedIn.getRealName());
        return sessionSoldier;
    }


    private void postHandle(final HttpServletRequest request, final RequestObjFO requestObj,final BaseResponse remoteResponse){
        if ((SoldierConstant.RPC_SERVICE_INTERFACE_ALIPAY_LIFE_REGISTER_OR_LOGIN.equals(requestObj.getOperation())
            /*|| SoldierConstant.RPC_SERVICE_INTERFACE_ALIPAY_REGISTER.equals(requestObj.getOperation())
            || SoldierConstant.RPC_SERVICE_INTERFACE_ALIPAY_LOGIN.equals(requestObj.getOperation())*/)
            && remoteResponse.isSuccess() && remoteResponse.getDto()!=null){
            final JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(remoteResponse.getDto()));
            final LoggedInSoldierPersistentVO loggedInSoldierPersistentVO = JSON.parseObject(jsonObject.getString(SoldierConstant.JSON_KEY_LOGGEDIN_SOLDIER_PERSISTENT_INFO),
                    LoggedInSoldierPersistentVO.class);
            BizCheckUtil.checkNotNull(loggedInSoldierPersistentVO,"请求登录返回的对象非法");
            BizCheckUtil.checkNotBlank(loggedInSoldierPersistentVO.getToken(),"请求登录返回的对象属性token非法");

            cacheManager.setCommonValue(SoldierConstant.CACHE_KEY_LOGGEDIN_SOLDIER_PREFIX + loggedInSoldierPersistentVO
                    .getToken(), loggedInSoldierPersistentVO);
        }

        if ((StringUtils.equals(SoldierConstant.RPC_SERVICE_INTERFACE_LOGOUT, requestObj.getOperation())
            || StringUtils.equals(SoldierConstant.RPC_SERVICE_INTERFACE_PWD_MODIFY, requestObj.getOperation())) && remoteResponse.isSuccess()){
            cacheManager.removeCommonValue(SoldierConstant.CACHE_KEY_LOGGEDIN_SOLDIER_PREFIX + request.getHeader(SoldierConstant.SOLDIER_TOKEN_NAME));
        }
    }

}
